# app/routes/outcomes.py
from flask import Blueprint, request, jsonify, current_app
from app import db
from app.models import Outcome, OutcomeType, User
from app.routes.auth import token_required # 导入认证装饰器

bp = Blueprint('outcomes', __name__)

# --- 成果 API ---

@bp.route('', methods=['POST'])
@token_required # 需要登录才能提交成果
def submit_outcome(current_user):
    """提交新的成果"""
    data = request.get_json()
    if not data or 'type_id' not in data or 'data' not in data:
        return jsonify({"error": "缺少 type_id 或 data 字段"}), 400

    # 检查 type_id 是否存在 (注意: OutcomeType id 是 String)
    # !! 如果 OutcomeType 的 id 真的是字符串，这里的 .get() 应该直接用字符串 !!
    # !! 如果前端传的是数字，后端可能需要转换或前端确保传字符串 !!
    outcome_type = OutcomeType.query.get(str(data['type_id'])) # 假设前端可能传数字，强制转str
    if not outcome_type:
         # 为了调试，打印出尝试获取的 ID
        print(f"Debug: OutcomeType not found for ID: {data['type_id']} (type: {type(data['type_id'])})")
        return jsonify({"error": f"无效的成果类型 ID: {data['type_id']}"}), 400


    # 简单验证成果数据是否为 JSON 对象
    if not isinstance(data.get('data'), dict):
         return jsonify({"error": "成果 data 必须是一个 JSON 对象"}), 400

    # !! 实际应用中，这里应该根据 outcome_type.config_data (或单独的 schema 字段) 验证 data 字段 !!

    new_outcome = Outcome(
        outcome_type_id=outcome_type.id, # 使用从数据库查到的 type_id，确保一致性
        submitter_id=current_user.id, # 从 token_required 注入的 current_user 获取 ID
        outcome_data=data['data'], # 注意模型字段名是 outcome_data
        status='待审核' # 初始状态
        # submit_date 会自动使用 default 值
    )
    db.session.add(new_outcome)
    try:
        db.session.commit()
        return jsonify(new_outcome.to_dict()), 201
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error submitting outcome: {e}") # 使用 current_app.logger 记录错误
        import traceback
        traceback.print_exc() # 打印错误栈到控制台
        return jsonify({"error": "提交成果时发生内部错误"}), 500


@bp.route('', methods=['GET'])
@token_required # 需要登录才能查看成果
def get_outcomes(current_user):
    """获取成果列表 (带分页和过滤)"""
    # 分页参数
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 10, type=int)
    per_page = min(per_page, 100) # 限制每页最大数量

    query = Outcome.query

    # 过滤条件 (可以根据需要扩展)
    status_filter = request.args.get('status')
    # 注意: OutcomeType ID 在模型中是 String，所以这里获取时不应指定 type=int
    type_id_filter = request.args.get('type_id')
    submitter_id_filter = request.args.get('submitter_id', type=int)

    if status_filter:
        query = query.filter(Outcome.status == status_filter)
    if type_id_filter:
        query = query.filter(Outcome.outcome_type_id == type_id_filter) # 模型字段是 outcome_type_id

    # 权限控制：普通用户只能看到自己的成果，管理员可以看到所有
    # !! 假设 User 模型中的 role 字段值为 'normal' 和 'admin' !!
    if current_user.role == 'normal':
        query = query.filter(Outcome.submitter_id == current_user.id)
    elif current_user.role == 'admin' and submitter_id_filter:
         # 管理员可以按提交者过滤
         query = query.filter(Outcome.submitter_id == submitter_id_filter)


    # --- 修改排序字段 ---
    # 排序 (按提交日期降序)
    query = query.order_by(Outcome.submit_date.desc()) # 使用 submit_date 替换 created_at
    # --- 结束修改 ---

    # 执行分页查询
    try:
        paginated_outcomes = query.paginate(page=page, per_page=per_page, error_out=False)
    except Exception as e:
        current_app.logger.error(f"Error during outcome pagination: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({"error": "查询成果时发生错误"}), 500


    results = [o.to_dict() for o in paginated_outcomes.items]

    return jsonify({
        'outcomes': results,
        'total_pages': paginated_outcomes.pages,
        'current_page': paginated_outcomes.page,
        'total_items': paginated_outcomes.total,
        'per_page': paginated_outcomes.per_page
    }), 200


@bp.route('/<int:id>', methods=['GET'])
@token_required # 需要登录
def get_outcome(current_user, id):
    """获取指定 ID 的成果详情"""
    outcome = Outcome.query.get_or_404(id)

    # 权限检查：管理员或成果提交者本人
    if current_user.role != 'admin' and outcome.submitter_id != current_user.id:
        return jsonify({"error": "无权查看此成果"}), 403

    return jsonify(outcome.to_dict()), 200

@bp.route('/<int:id>', methods=['PUT'])
@token_required # 需要登录
def update_outcome(current_user, id):
    """修改指定 ID 的成果"""
    outcome = Outcome.query.get_or_404(id)
    data = request.get_json()
    if not data:
        return jsonify({"error": "请求体不能为空"}), 400

    # 权限检查：只有管理员或提交者在“待审核”状态下才能修改
    can_edit = False
    if current_user.role == 'admin':
        can_edit = True
    elif outcome.submitter_id == current_user.id and outcome.status == '待审核':
        can_edit = True

    if not can_edit:
        return jsonify({"error": "无权修改此成果或当前状态不允许修改"}), 403

    # 允许修改的字段
    if 'data' in data:
        if not isinstance(data.get('data'), dict):
             return jsonify({"error": "成果 data 必须是一个 JSON 对象"}), 400
        # !! 同样，这里应该根据 schema 验证 data !!
        outcome.outcome_data = data['data'] # 模型字段是 outcome_data

    # 管理员可以修改状态和评论
    if current_user.role == 'admin':
        if 'status' in data:
            allowed_statuses = ['待审核', '已通过', '已驳回']
            if data['status'] not in allowed_statuses:
                return jsonify({"error": f"无效的状态值，允许的值: {', '.join(allowed_statuses)}"}), 400
            outcome.status = data['status']

            # 如果状态改变，更新 review_date
            if outcome.status in ['已通过', '已驳回']:
                 outcome.review_date = db.func.current_date() # 使用数据库当前日期
            else: # 改回待审核
                 outcome.review_date = None

        # 注意模型字段是 rejection_reason
        if 'rejection_reason' in data:
             outcome.rejection_reason = data['rejection_reason'] if data.get('rejection_reason') else None
        elif outcome.status != '已驳回':
             outcome.rejection_reason = None # 通过或改回待审核时清空原因

    try:
        db.session.commit()
        return jsonify(outcome.to_dict()), 200
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error updating outcome {id}: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({"error": "更新成果时发生内部错误"}), 500


# 可以为管理员单独创建一个审核接口，逻辑更清晰
@bp.route('/<int:id>/review', methods=['PUT'])
@token_required(required_role='admin') # 确保 token_required 支持角色参数
def review_outcome(current_user, id):
    """管理员审核成果 (修改状态和评论)"""
    outcome = Outcome.query.get_or_404(id)
    data = request.get_json()
    if not data or 'status' not in data:
         return jsonify({"error": "必须提供 status 字段"}), 400

    allowed_statuses = ['已通过', '已驳回'] # 审核操作只允许这两个状态
    if data['status'] not in allowed_statuses:
        return jsonify({"error": f"无效的审核状态值，允许的值: {', '.join(allowed_statuses)}"}), 400

    outcome.status = data['status']
    outcome.review_date = db.func.current_date() # 设置审核日期

    if outcome.status == '已驳回':
        # 注意模型字段是 rejection_reason
        outcome.rejection_reason = data.get('rejection_reason') # 驳回时可以添加原因
    else:
        outcome.rejection_reason = None # 通过时清空原因

    try:
        db.session.commit()
        return jsonify(outcome.to_dict()), 200
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error reviewing outcome {id}: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({"error": "审核成果时发生内部错误"}), 500


@bp.route('/<int:id>', methods=['DELETE'])
@token_required # 需要登录
def delete_outcome(current_user, id):
    """删除指定 ID 的成果"""
    outcome = Outcome.query.get_or_404(id)

    # 权限检查：管理员或提交者在“待审核”状态下才能删除
    can_delete = False
    if current_user.role == 'admin':
        can_delete = True
    elif outcome.submitter_id == current_user.id and outcome.status == '待审核':
        can_delete = True

    if not can_delete:
         return jsonify({"error": "无权删除此成果或当前状态不允许删除"}), 403

    try:
        db.session.delete(outcome)
        db.session.commit()
        return '', 204 # No Content
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error deleting outcome {id}: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({"error": "删除成果时发生内部错误"}), 500

